<?php
namespace kernel\library;

class Es7
{
    //全部使用curl取代
    protected $host = null;//连接地址 例如'http://user:pass@localhost:9200'
    
    //单例属性
    protected static $ins = [];
    // 构造函数私有化
    final protected function __construct()
    {}
    /**
     * .单例连接ES
     * @return static
     */
    static public function getInstance($host)
    {
        $class = get_called_class();
        if (isset(self::$ins[$class])) {
            return self::$ins[$class];
        }
        $self = new static();
        self::$ins[$class] = $self;
        $self->host = $host;
        return $self;
    }
    
    protected $index = null;//数据库
    protected $_id = null;//id
    protected $query = [];//查询条件
    protected $bulk = '';//批量操作
    /**
     * .指定库 单库单表
     * @param string $index
     * @return \kernel\library\Es7
     */
    public function index(string $index){
        $this->index = $index;
        return $this;
    }
    
    /**
     * _id
     * @param string $_id
     * @return \kernel\library\Es7
     */
    public function _id(string $_id){
        $this->_id = $_id;
        return $this;
    }
    
    /**
     * .设置精准查询条件 
     * @param array $arr
     * @return \kernel\library\Es7
     */
    public function term(array $arr){
        $api = $this->host.'/'.$this->index.'/'.$this->index.'/_search';
        $this->query = array_merge($this->query, ['term' => $arr]);
        return $this;
    }
    
    public function wildcard(array $arr){
        $this->query = array_merge($this->query, ['term' => $arr]);
        return $this;
    }
    /**
     * .添加数据
     * @param array $body
     * @param bool $bulk
     */
    public function add(array $body, bool $bulk = false){
        //批量处理
        if($bulk){
            $create = ['_index' => $this->index, '_type' => $this->index];
            
            if($this->_id){
                $create['_id'] = $this->_id;
            }
            
            $this->bulk .= json_encode(['create' => $create], JSON_UNESCAPED_UNICODE)."\n";//设置头
            $this->bulk .= json_encode($body, JSON_UNESCAPED_UNICODE)."\n";//设置body数据
            return;
        }
        
        $api = $this->host.'/'.$this->index.'/'.$this->index;//非要加type
        if($this->_id){
            $api .= '/'.$this->_id;
        }
        return Curl::post($api, $body, true, ["Content-Type:application/json"]);
    }
    
    //思考的问题 批量写入 批量更新
    public function bulkData(string $event, array $body){
        $data = array_merge($body, [
            '_index' => $this->index,
            '_type' => $this->index,
        ]);
        if($this->_id){
            $data['_id'] = $this->_id; 
        }
        $this->bulkData[] = [
            $event => $data
        ];
        
    }
    /**
     * .执行批量操作
     * @return mixed
     */
    public function bulk(){
        if($this->bulk == false){
            Error::setError('bulk数据未设置', 500);
        }
        $api = $this->host.'/_bulk';
        return Curl::post($api, $this->bulk, true, ["Content-Type:application/json"]);
    }
    /**
     * .删除指定id数据
     * @return mixed
     */
    public function delete(bool $bulk = false){
        //批量删除 仅支持id
        if($bulk){
            
            if($this->_id == false){
                Error::setError('批量删除只支持_id参数', 500);
            }
            $delete = ['_index' => $this->index, '_type' => $this->index, '_id' => $this->_id];
            $this->bulk .= json_encode(['delete' => $delete], JSON_UNESCAPED_UNICODE)."\n";
            return ;
        }
        
        
        $api = $this->host.'/'.$this->index.'/'.$this->index;//非要type
        if($this->_id){
            $api .= '/'.$this->_id;
        }
        $params = [];
        //如果有查询条件按查询条件删除
        if($this->query){
            $params = [
                'query' => $this->query
            ];
        }
        return Curl::delete($api, $params, true);
    }
    /**
     * .更新 支持id更新 支持查询条件更新
     * @param string $id
     * @param array $body
     * @param bool $bulk
     * @return mixed
     */
    public function update(array $body, bool $bulk = false){
        //批量更新
        if($bulk){
            if($this->_id == false){
                Error::setError('批量更新只支持_id参数', 500);
            }
            $update = ['_index' => $this->index, '_type' => $this->index, '_id' => $this->_id];
            $this->bulk .= json_encode(['update' => $update], JSON_UNESCAPED_UNICODE)."\n";
            $this->bulk .= json_encode(['doc' => $body], JSON_UNESCAPED_UNICODE)."\n";
            return ;
        }
        
        
        $api = $this->host.'/'.$this->index.'/'.$this->index;//非要加type
        //根据主键id更新
        if($this->_id){
            $api .= '/'.$this->_id;
            $api .= '/_update';
            $updateData = ['doc' => $body];//更新参数
        }
        
        
        //通过查询更新
        if($this->query && $this->_id == false){
            $updateData['script'] = [
                'source' => '',
                'lang' => "painless"
            ];
            
            foreach($body as $k => $v){
                $updateData['script']['source'] .= "ctx._source.{$k} = '{$v}'";
            }
            $updateData['script']['source'] = rtrim($updateData['script']['source'], ';');
            $updateData['script']["lang"] = "painless";
            $updateData['query'] = $this->query;
            $api .= '/_update_by_query';
            //更新成功
        }
        return Curl::post($api, $updateData, true, ["Content-Type:application/json"]);
    }
    /**
     * .查询索引 搞定 数据列表 + 加搜索
     * @param number $page
     * @param number $limit
     * @return mixed
     */
    public function getList($page = 1, $limit = 20){
        $page = ($page < 1 ) ? 1 : $page;
        $page = ($page - 1) * $limit;
        $api = $this->host.'/'.$this->index.'/_search?pretty&size='.$limit.'&from='.$page;//不用加type
        $params = ['sort' => [
            '_id' => ['order' => 'desc'],//使用id倒序
        ]];
        if($this->query){
            $params += [
                'query' => $this->query
            ];
        }
        return Curl::get($api, $params, true, ["Content-Type:application/json"]);
    }
    
    public function finder($page = 1, $limit = 20){
        //echo rand(0,999);
        $res = $this->getList($page, $limit);
        return [
            'errorcode' => '0',
            'errormsg' => '成功',
            'data' => [
                'total' => $res['hits']['total']['value'],
                'current_page' => $page,
                'data' => $res['hits']['hits']
            ],
            'runtime' => microtime(true) - BASICS_STIME
        ];
    }
    
    /**
     * .清空
     * @return mixed
     */
    public function clearn(){
        $api = $this->host.'/'.$this->index;//不要type
        $params = [];
        return Curl::delete($api, $params, true, ["Content-Type:application/json"]);
    }
    /**
     * .清空所有
     * @return mixed
     */
    public function clearnAll(){
        $api = $this->host.'/_all';//不要type
        $params = [];
        return Curl::delete($api, $params, true, ["Content-Type:application/json"]);
    }
    /**
     * .获取所有index
     * @return mixed
     */
    public function allIndex(){
        $api = $this->host.'/_cat/indices?format=json';
        return Curl::get($api, [], true, ["Content-Type:application/json"]);
    }
    /**
     * .获取某个索引的状态信息
     * @return mixed
     */
    public function stats(){
        $api = $this->host.'/'.$this->index.'/_stats';
        return Curl::get($api, [], true, ["Content-Type:application/json"]);
    }
    
    
    
    //做一个搜索的分页 如果没有搜索的话应该是显示所有*只有模糊搜索
//     public function finder(){   
//         $api = $this->host.'/'.$this->index.'/'.$this->type.'/_search';
//         $params = [
//             'query' => $this->query
//         ];
//         $res = Curl::get($api, $params, true, ["Content-Type:application/json"]);
//         return $res;
//     }
    
    
    
    
    // 防止克隆对象
    private function __clone()
    {}
}

